#pragma once
#include "Common.hpp"
#include "Channel.hpp"

#define MAX_EPOLL_EVENTS_DEFAULT 1024
class Poller
{
private:
    // int _epfd = -1;//修改前
    int _epfd;
    struct epoll_event _evs[MAX_EPOLL_EVENTS_DEFAULT];
    std::unordered_map<int, Channel *> _channels; // 映射表
private:
    void Update(Channel *channel, int op)
    {
        // 谁要修改监控的事件? channel!
        int fd = channel->Fd();
        struct epoll_event event;
        event.data.fd = fd;
        event.events = channel->Events();
        int n = ::epoll_ctl(_epfd, op, fd, &event);
        if (n < 0)
        {
            LOG(ERROR, "修改epoll异常!,异常信息: %s,%d,fd:%d\n", strerror(errno), op, fd);
            return;
        }
        return;
    }
    // 判断channel是否被监控 -- 修改前
    // bool HasChannel(int fd)
    // {
    //     auto iter = _channels.find(fd);
    //     if (iter == _channels.end())
    //     {
    //         return false;
    //     }
    //     return true;
    // }
    bool HasChannel(Channel *channel)
    {
        auto iter = _channels.find(channel->Fd());
        if (iter == _channels.end())
        {
            return false;
        }
        return true;
    }

public:
    Poller()
    {
        _epfd = ::epoll_create(MAX_EPOLL_EVENTS_DEFAULT);
        if (_epfd < 0)
        {
            LOG(FATAL, "创建epoll异常!\n");
            abort();
        }
        LOG(DEBUG, "创建eoll完毕! _epfd = %d\n", _epfd);
    }
    // 增加否则修改
    void UpdateEvent(Channel *channel)
    {
        // printf("开始epoll的UpdateEvent()调用!,sockfd = %d\n",channel->Fd());
        // LOG(DEBUG,"开始epoll的UpdateEvent()调用!,sockfd = %d\n",channel->Fd());
        // if (!HasChannel(channel))--修改前
        // {
        //     // 增加本次监控
        //     LOG(DEBUG,"开始EPOLL_CTL_ADD\n");
        //     _channels.insert(std::make_pair(channel->Fd(), channel));
        //     return Update(channel, EPOLL_CTL_ADD);
        // }
        // else
        // {
        //     // 本次为修改已存在的事件监控
        //     LOG(DEBUG,"开始EPOLL_CTL_MOD\n");
        //     return Update(channel, EPOLL_CTL_MOD);
        // }
        bool ret = HasChannel(channel);
        if (!ret)
        {
            // 增加本次监控
            LOG(DEBUG, "开始EPOLL_CTL_ADD\n");
            _channels.insert(std::make_pair(channel->Fd(), channel));
            return Update(channel, EPOLL_CTL_ADD);
        }
        // 本次为修改已存在的事件监控
        LOG(DEBUG, "开始EPOLL_CTL_MOD\n");
        return Update(channel, EPOLL_CTL_MOD);
    }
    // 移除该channel的事件监控
    void RemoveEvent(Channel *channel)
    {
        auto iter = _channels.find(channel->Fd());
        if (iter != _channels.end())
        {
            _channels.erase(iter);
        }
        Update(channel, EPOLL_CTL_DEL);
    }
    void Poll(std::vector<Channel *> *active)
    {
        LOG(DEBUG, "开始监控\n");
        // 开始监控
        int nfds = ::epoll_wait(_epfd, _evs, MAX_EPOLL_EVENTS_DEFAULT, -1); // TODO
        if (nfds < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            LOG(ERROR, "epoll_wait异常!\n");
            abort();
        }
        LOG(DEBUG, "%d 个描述符就绪!\n", nfds);
        for (int i = 0; i < nfds; i++)
        {
            int fd = _evs[i].data.fd;
            uint32_t revents = _evs[i].events;
            auto iter = _channels.find(fd);
            assert(iter != _channels.end());
            iter->second->SetREvents(revents);
            active->push_back(iter->second);
        }
        return;
    }
};